package com.lesliefang.abcdisasm

import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.testFramework.LightVirtualFile
import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
import java.util.concurrent.TimeUnit
import java.nio.charset.StandardCharsets

/**
 * 针对.abc文件的右键菜单Action
 */
class AbcFileAction : AnAction() {
    override fun getActionUpdateThread(): ActionUpdateThread {
        return  ActionUpdateThread.BGT
    }

    override fun actionPerformed(e: AnActionEvent) {
        val project = e.project ?: return
        val virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE) ?: return
        
        try {
            // 调用命令行工具处理文件并获取输出文件路径
            val outputFilePath = processAbcFile(virtualFile.path)
            
            // 读取输出文件内容并在新编辑器窗口中显示
            val content = Files.readString(Paths.get(outputFilePath), StandardCharsets.UTF_8)
            showResultInEditor(project, virtualFile.name, content)
            
        } catch (ex: Exception) {
            Messages.showErrorDialog(
                project,
                "Error processing ABC file: ${ex.message ?: "Unknown error"}",
                "ABC Disassembly Error"
            )
        }
    }
    
    /**
     * 调用命令行工具处理abc文件
     * @param filePath 输入文件路径
     * @return 输出文件路径
     */
    private fun processAbcFile(filePath: String): String {
        // 获取插件路径下的工具
//        val pluginPath = PathManager.getPluginsPath()
        val homePath = PathManager.getHomePath()
        val toolchainsPath = Paths.get(homePath,"sdk","default","openharmony","toolchains")
        val osName = System.getProperty("os.name").lowercase()

        // 根据操作系统选择合适的工具
        val toolName = when {
            osName.contains("win") -> "ark_disasm.exe"
            else -> "ark_disasm" // 默认使用shell脚本
        }

        val toolPathFile = File(toolchainsPath.toFile(),toolName)
        if(!toolPathFile.exists()) {
            throw RuntimeException("$toolPathFile not exists")
        }

        val toolPath = toolPathFile.absolutePath

        // 创建临时输出文件
        val inputFile = File(filePath)
        val tempDir = Files.createTempDirectory("abcdisasm").toFile()
        val outputFile = File(tempDir, "${inputFile.nameWithoutExtension}_disasm.txt")
        
        // 根据操作系统构建命令
        val command = if (osName.contains("win")) {
            listOf("cmd", "/c", toolPath, filePath, outputFile.absolutePath)
        } else if (osName.contains("mac")) {
            // 在Mac上检测二进制文件架构并决定是否使用Rosetta 2
            val binaryArch = getBinaryArchitecture(toolPath)
            if (binaryArch == "x86_64") {
                // x86_64架构的二进制文件，在Apple Silicon Mac上需要使用Rosetta 2
                listOf("arch", "-x86_64", toolPath, filePath, outputFile.absolutePath)
            } else {
                // arm64架构或其他架构，直接运行
                listOf(toolPath, filePath, outputFile.absolutePath)
            }
        } else {
            listOf("bash", toolPath, filePath, outputFile.absolutePath)
        }
        
        val processBuilder = ProcessBuilder(command)
        processBuilder.directory(File(filePath).parentFile)
        
        val process = processBuilder.start()
        
        // 等待进程完成，最多等待30秒
        val finished = process.waitFor(30, TimeUnit.SECONDS)
        
        if (!finished) {
            process.destroyForcibly()
            throw RuntimeException("Command execution timeout")
        }
        
        val exitCode = process.exitValue()
        val errorOutput = process.errorStream.bufferedReader().readText()
        
        if (exitCode != 0) {
            throw RuntimeException("Command failed with exit code $exitCode: $errorOutput")
        }
        
        // 检查输出文件是否存在
        if (!outputFile.exists()) {
            throw RuntimeException("Output file was not created by the command")
        }
        
        return outputFile.absolutePath
    }
    
    /**
     * 获取二进制文件的架构信息
     * @param binaryPath 二进制文件路径
     * @return 架构字符串（如 "x86_64", "arm64" 等）
     */
    private fun getBinaryArchitecture(binaryPath: String): String {
        return try {
            val process = ProcessBuilder("file", binaryPath).start()
            val output = process.inputStream.bufferedReader().readText()
            process.waitFor()
            
            when {
                output.contains("x86_64") -> "x86_64"
                output.contains("arm64") -> "arm64"
                output.contains("i386") -> "i386"
                else -> "unknown"
            }
        } catch (e: Exception) {
            // 如果检测失败，默认假设是x86_64（保持向后兼容）
            "x86_64"
        }
    }
    
    /**
     * 在新编辑器窗口中显示处理结果
     */
    private fun showResultInEditor(project: Project, originalFileName: String, content: String) {
        // 创建虚拟文件来显示结果
        val resultFileName = "${originalFileName}_disasm.txt"
        val virtualFile = LightVirtualFile(resultFileName, content)
        
        // 在编辑器中打开文件
        FileEditorManager.getInstance(project).openFile(virtualFile, true)
    }

    override fun update(e: AnActionEvent) {
        val virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE)
        val isAbcFile = virtualFile?.let { file ->
            !file.isDirectory && file.name.endsWith(".abc")
        } ?: false
        
        // 设置菜单项的可见性和可用性
        e.presentation.isEnabledAndVisible = isAbcFile
        
        // 如果是abc文件，确保菜单项文本正确显示
        if (isAbcFile) {
            e.presentation.text = AbcDisasmBundle.message("action.abc.file.text")
            e.presentation.description = AbcDisasmBundle.message("action.abc.file.description")
        }
    }
}